package io.gitee.mingbaobaba.apijson.querycondition.query.conditions;


import io.gitee.mingbaobaba.apijson.querycondition.query.exception.ConditionException;

import java.util.Objects;
import java.util.function.Consumer;

/**
 * <p>基于Lambda构建查询参数</p>
 *
 * @author yingsheng.ye
 * @version 1.0.0
 * @since 2023/6/19 18:06
 */

public class ApiJsonQueryLambdaWrapper<T> extends AbstractQueryWrapper<T, ColumnUtil.SFunction<T, ?>, ApiJsonQueryLambdaWrapper<T>> implements ApiJsonQuery {

    /**
     * select 指定查询列字段
     *
     * @param columns 查询列
     * @return ApiJsonQueryLambdaWrapper<T>
     */
    @SafeVarargs
    @Override
    public final ApiJsonQueryLambdaWrapper<T> select(ColumnUtil.SFunction<T, ?>... columns) {
        return select(true, columns);
    }

    /**
     * select 指定查询列字段
     *
     * @param condition 条件false忽略
     * @param columns   查询列
     * @return ApiJsonQueryLambdaWrapper<T>
     */
    @SafeVarargs
    @Override
    public final ApiJsonQueryLambdaWrapper<T> select(boolean condition, ColumnUtil.SFunction<T, ?>... columns) {
        if (condition) {
            for (ColumnUtil.SFunction<T, ?> column : columns) {
                columnList.add(ColumnUtil.getName(column));
            }
        }
        return typedThis;
    }

    /**
     * 添加条件
     *
     * @param condition 条件false忽略
     * @param column    列
     * @param keyword   连接条件
     * @param val       值
     * @return ApiJsonQueryLambdaWrapper<T>
     */
    @Override
    protected ApiJsonQueryLambdaWrapper<T> addCondition(boolean condition, ColumnUtil.SFunction<T, ?> column, EnumKeyword keyword, Object val) {
        if (condition) {
            this.conditionHandle(new Condition(parseName(column), keyword, val));
        }
        return typedThis;
    }

    /**
     * 添加聚合条件
     *
     * @param condition 条件false忽略
     * @param column    列
     * @param keyword   连接条件
     * @param val       值
     * @return ApiJsonQueryLambdaWrapper<T>
     */
    @Override
    protected ApiJsonQueryLambdaWrapper<T> addAggFunc(boolean condition, ColumnUtil.SFunction<T, ?> column, EnumKeyword keyword, Object val) {
        if (condition) {
            this.aggFuncHandle(keyword, parseName(column), val);
        }
        return typedThis;
    }

    /**
     * 添加分组聚合条件
     *
     * @param condition 条件false忽略
     * @param column    列
     * @param keyword   连接条件
     * @return ApiJsonQueryLambdaWrapper<T>
     */
    @Override
    protected ApiJsonQueryLambdaWrapper<T> addGroupFunc(boolean condition, ColumnUtil.SFunction<T, ?> column, EnumKeyword keyword) {
        if (condition) {
            this.groupFuncHandle(keyword, parseName(column));
        }
        return typedThis;
    }

    /**
     * 添加排序条件
     *
     * @param condition 条件
     * @param column    列
     * @param keyword   关键字
     * @param s         排序值 +升序 -降序
     * @return ApiJsonQueryLambdaWrapper
     */
    @Override
    protected ApiJsonQueryLambdaWrapper<T> addOrderByFunc(boolean condition, ColumnUtil.SFunction<T, ?> column, EnumKeyword keyword, String s) {
        if (condition) {
            this.orderByFuncHandle(keyword, parseName(column) + s);
        }
        return typedThis;
    }

    /**
     * 构建一个子实例
     *
     * @return ApiJsonQueryLambdaWrapper<T>
     */
    @Override
    protected ApiJsonQueryLambdaWrapper<T> instance() {
        return new ApiJsonQueryLambdaWrapper<>();
    }

    /**
     * 解析列名
     *
     * @param column ColumnUtil.SFunction<T, ?>
     * @return 列名
     */
    private String parseName(ColumnUtil.SFunction<T, ?> column) {
        return null == column ? null : ColumnUtil.getName(column);
    }


    /**
     * join关联
     *
     * @param tableName 关联表名
     * @param column    列名
     * @param consumer  Consumer
     * @param <E>       泛型
     * @return ApiJsonQueryLambdaWrapper
     */
    public <E> ApiJsonQueryLambdaWrapper<T> join(Class<E> tableName, ColumnUtil.SFunction<E, ?> column,
                                                 ColumnUtil.SFunction<T, ?> relColumn, Consumer<JoinWrapper<E>> consumer) {
        if (Objects.nonNull(joinOperation)) {
            throw new ConditionException("join只支持单个配置");
        }
        final JoinWrapper<E> instance = joinInstance();
        instance.setColumn(ColumnUtil.getName(column));
        instance.setRelColumn(ColumnUtil.getName(relColumn));
        instance.setTableName(tableName);
        if (null != consumer) {
            consumer.accept(instance);
        }
        joinOperation = instance;
        return typedThis;
    }

    /**
     * join关联
     *
     * @param tableName 表名
     * @param column    列名
     * @param relColumn 关联列名
     * @param <E>       泛型
     * @return ApiJsonQueryLambdaWrapper<T>
     */
    public <E> ApiJsonQueryLambdaWrapper<T> join(Class<E> tableName, ColumnUtil.SFunction<E, ?> column,
                                                 ColumnUtil.SFunction<T, ?> relColumn) {
        return join(tableName, column, relColumn, null);
    }


    /**
     * 构建一个join连接实例
     *
     * @param <E> 泛型
     * @return JoinWrapper<E>
     */
    @Override
    protected <E> JoinWrapper<E> joinInstance() {
        return new JoinWrapper<>();
    }

}
